home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
cexpert.zip
/
MCH5.LST
< prev
next >
Wrap
File List
|
1990-09-15
|
10KB
|
338 lines
Listing 5-1 Unification for Prolog
/************************************************************************
Unification Implementation
Convention: Substitutions returned by unify-xxx are for the FIRST argument.
It makes no sense to mix substitutions of two expressions!! the variable names
are relative to each expression, so that it makes no sense to mix them.
Ex: (unify-pred '(p ?x 1) '(p 2 ?x)) should work fine, but what to return?
PRED is LIST w/first term nonvar symbol assumed
PROP is EXP w/first term nonvar symbol assumed, rest terms are PROPS.
Could make all unify-xxx fns faster by making loop, instead of recursion.
***********************************************************************/
/*-----------------------------------------------------include------------*/
#include <stdio.h>
#include "cons.h"
#include "goal.h"
/*------------------------------------------------------unify_equal()------*/
/*
** unify_equal: Does not handle varterms
** This is the KEY, inner loop operation performed for unification
** in the reasoning system. As such, we would like to make it as efficient
** as possible. Two terms are considered equal for the purposes of
** unification if one of two conditions are met:
** * They are #'equal (a la lisp)
**
** * They denote an equivalent number
**
** Example:unify-equal ('3, '3) --> ((t t))
** unify-equal ('p, ?X) --> NIL
*/
cons *unify_equal(term1,term2)
cons *term1,*term2;
{
return (!strcmp(term1->car.s,term2->car.s)) ? mklist2("t","t") : NULL;
}
/*---------------------------------------------------unify_term_c()------*/
/*
** unify_term_c:
** Term unification, with second arg unsubstitutable.
** Example: unify_term_c(?a, 3) --> ((?a . 3))
** unify_term_c(3, ?a) --> nil
**
** Used for slot and variable values.
*/
cons *unify_term_c(accom_term,const_term)
cons *accom_term,*const_term;
{
if (variablep(accom_term)) {
return mklist2(accom_term->car.s,const_term->car.s);
} else {
return unify_equal(accom_term,const_term);
}
}
/*---------------------------------------------------unify_term()------*/
/*
** unify_term: Handles var-terms
** Used for predicate EQUAL.
**
** Example: unify_term(?a, 3) --> ((?a . 3))
** unify_term(3, ?a) --> ((?a . 3))
**
*/
cons *unify_term(term1,term2)
cons *term1,*term2;
{
if (variablep(term1)) {
return mklist2(term1->car.s,term2->car.s);
} else if (variablep(term2)) {
return mklist2(term2->car.s,term1->car.s);
} else {
return unify_equal(term1,term2);
}
}
/*---------------------------------------------------unify_pred_c()------*/
/*
** unify_pred_c: Predicate Unification with second predicate constant.
** finds substitution s that makes accom-exp . s = const-exp
**
** Example: unify-pred-C '(P ?X 5) '(P 3 ?y) ==> nil
** unify-Pred-C '(P ?X ?Y) '(P 2 ?Y) ==> '((?X . 2))
**
** Typically first arg is goal and second is fact w/no vars.è*/
cons *unify_pred_c(accom_pred,const_pred)
cons *accom_pred,*const_pred;
{
if(equal(accom_pred,const_pred))
return ltwotees();
if (length(const_pred) == length(accom_pred) &&
!strcmp(const_pred->car.p->car.s,accom_pred->car.p->car.s)) {
return unify_list_c_1(accom_pred->cdr,const_pred->cdr);
} else {
return NULL;
}
}
/*---------------------------------------------------unify_list_c_1()------*/
/*
** unify_list_c_1() Aux fn that does not check length.
** This is an auxiliary for unify_pred_c.
*/
cons *unify_list_c_1 (ap,cp)
cons *ap,*cp;
{
cons *subst = NULL;
cons *apterm = ap->car.p;
cons *cpterm = cp->car.p;
cons *tmp;
while (apterm != NULL) {
if (tmp = unify_equal(apterm,cpterm)) {
killcons(tmp);
} else if (variablep(apterm)) {
tmp = mkcons(CAR_LIST,mklist2(apterm->car.s,cpterm->car.s),NULL);
subst = nconc(subst,tmp);
} else {
return NULL;
}
ap = ap->cdr; cp = cp->cdr;
apterm = ap->car.p;
cpterm = cp->car.p;
}
if (subst == NULL) {
return mkcons(CAR_LIST,mklist2("t","t"),NULL);
} else {
return subst;
}
}
/*---------------------------------------------------unify_pred_nv()------*/è
/*
** unify_pred_nv(): Like U-P, but only returns substitution for terms
** that are nonvar in const_pred. Used in backward-chain.
**
** Example (unify_pred_nv ((p 1 ?x ?z),(p ?y 1 ?x))) --> (((?x 1))((?x z)))
**
** the second value returned is for the terms that are var in both (for use
** in translating prev-substs.)
*/
cons *unify_pred_nv(accom_pred,const_pred)
cons *accom_pred,*const_pred;
{
if(equal(accom_pred,const_pred))
return mkcons(CAR_LIST,ltwotees(),mkcons(CAR_LIST,ltwotees(),NULL));
if (length(const_pred) == length(accom_pred) &&
!strcmp(const_pred->car.p->car.s,accom_pred->car.p->car.s)) {
return unify_list_nv_1(accom_pred->cdr,const_pred->cdr);
} else {
return NULL;
}
}
/*-----------------------------------------------unify_list_nv_1()------*/
/*
** unify_list_nv_1(): Aux fn that does not check length.
*/
cons *unify_list_nv_1(ap, cp)
cons *ap,*cp;
{
cons *subst = NULL,*subst2 = NULL;
cons *apterm = ap->car.p;
cons *cpterm = cp->car.p;
cons *tmp,*retval;
while (apterm != NULL) {
if (tmp = unify_equal(apterm,cpterm)) {
killcons(tmp);
} else if (variablep(cpterm)) {
if (variablep(apterm)) {
subst2 = nconc(subst2,mkcons(CAR_LIST,
mklist2(cpterm->car.s,apterm->car.s),
NULL));
}
} else if (variablep(apterm)) {
subst = nconc(subst,mkcons(CAR_LIST,
mklist2(apterm->car.s,cpterm->car.s),
NULL));
} else { return NULL;
}
ap = ap->cdr; cp = cp->cdr;
apterm = ap->car.p;
cpterm = cp->car.p;
}
return mkcons(CAR_LIST,
(subst == NULL) ? mkcons(CAR_LIST,mklist2("t","t"),NULL)
: subst,
mkcons(CAR_LIST,(subst2 == NULL) ? mkcons(CAR_LIST,
mklist2("t","t"),
NULL)
: subst2));
}
Listing 5-2 Backtracking Program
/**********************************************************************
Implementation of Backtracking
The first call to a conjunction will leave this data structure around.
#s(GOAL-STACK :GOAL (AND (Q ?Y) (P ?X)) :PREV-SUBSTS (((?Y . 1) (?X . 1)))
:GOAL-STACK (#s(GOAL-FRAME :GOAL (P ?X) :SIT ((?Y . 1)) :PS NIL
:ROC NIL :SOLN ((?X . 1)) :CERT 1.0)
#s(GOAL-FRAME :GOAL (Q ?Y) :SIT NIL :PS NIL
:ROC ((P ?X)) :SOLN ((?Y . 1))
:CERT 0.8)))
We save a goal stack for every conjunction that is called initially. When
that conjunction is called again, we use the same goal stack. Possible
problem: a conjunction called in two places might need two different goal
stacks!!
********************************************************************** */
/*------------------------------------------------------include-----------*/
#include <stdio.h>
#include <math.h>
#include "cons.h"
#include "goal.h"
/*------------------------------------------------------global variable---*/
Goal_Stack *GOAL_STACK; /*declare the global GOAL_STACK*/
/*------------------------------------------------------backtrack()--------*/
/*
** backtrak.c
** Description: This program is to implement backtrack step in reasoning.
*/
/* Gets another solution to the current goal. As above, only returns
** solution for strictly current goal. Caller should add s_i_t.
** If Once? is t, then backtracking will only happen by one frame.
*/
Ret_Pair *Backtrack(gs_obj,once)
Goal_Stack *gs_obj; /*goal stack object*/
int once; /*tried or not flag*/
/*------------------------------------------------------------------------*/
{
Ret_Pair *ret_pair; /*return pair: subst,cert*/
Ret_Pair *temp_pair1,*temp_pair2;
Goal_Frame *gf;
cons *new_prev_substs,*tmp1;
double *cert;
#ifdef DEBUG
printf("\nIn Backtrack");
printf("\ngs_obj ::");
print_goal_obj(gs_obj);
printf("\nonce == %d",once);
#endif
ret_pair = init_ret_pair(); /*initialize the return pair*/
temp_pair1 = init_ret_pair();
gf = pop_a_frame(gs_obj); /*pop a goal frame from goal_stack*/
if(gf != NULL) /*pop up success*/
{
new_prev_substs = mkcons(CAR_LIST,gf->soln,gf->ps);
temp_pair1 = achieve(gf->goal,new_prev_substs);
if(temp_pair1->subst != NULL)
{
gf->ps = new_prev_substs;
gf->soln = temp_pair1->subst;
gf->cert = temp_pair1->certainty;
push_a_frame(gf,gs_obj);
tmp1 = gf->sit;
temp_pair2 = Frwdtrack(gs_obj,
subst_prop(gf->roc,temp_pair1->subst),
nconc(tmp1,temp_pair1->subst),FALSE);
if(temp_pair2->subst != NULL)
{
tmp1 = temp_pair1->subst;
ret_pair->subst = nconc(tmp1,temp_pair2->subst);
Min(temp_pair1->certainty,temp_pair2->certainty,cert);
ret_pair->certainty = (*cert);
return ret_pair;
}
else
{
return Backtrack(gs_obj,once);
}
}
else if(once == FALSE)
{
return Backtrack(gs_obj,FALSE);
}
}
}